perm filename COMB3[1,RWF] blob
sn#728168 filedate 1983-09-23 generic text, type T, neo UTF8
Reading and printing of decimal numbers is not a primitive operatin on most
computers, so Pascal provides standard subalgorithms to handle most of the
common situations that arise. Now and then, however, a problem comes up
where the built-in mechanisms are inadequate, and the programmer must
explicitly handle the individual decimal digits of numbers moving to or
from files. Suppose we have a number N, known to be greater than 100,000
and less than 1,000,000, which we want to print punctuated with a comma
after the thousands digit, like `123,456'. The WRITE command for numbers
does not provide for this form, so the program will have to execute
WRITE(`,), preceded by something that writes out (say) 123, and followed by
something that writes 456.
We can calculate the numbers to be printed before and after the comma as N
DIV 1000 and N mod 1000 repectively, and if N is 123456, the command
WRITE(N DIV 1000:3,`,',N MOD 1000:3) prints
123,456
as desired. If N is 123004, however, we get an unpleasant surprise:
123, 4
because the WRITE command never prints leading zeroes. For the part of the
number that follows the comma, at least, we must work out the individual
digits, and print them separately. To get the tens digit requires two
steps. Taking N MOD 100 gives us the numerical value of the two right hand
digits (56 and 4 in the examples above), after which a division by 10 gives
the tens digit. To print a six digit integer N withut supressing leading
zeroes can be done with this subprogram:
D:=1000000;
FOR I:= 1 TO 6 DO
BEGIN
D:=D DIV 10; (*FIRST TIME 100000, LAST TIME 1*)
Q:=N DIV D; (*NEXT DIGIT ON N*)
WRITE(Q:1);
N:=N MOD D
END
where a comma can be inserted by inserting IF I=3 THEN WRITE (`,') after
the WRITE command.
Exercise
If we don't know that N is greater than 100,000, a more complicated
algorithm is needed. Write a program that will print N in one of these
forms:
1,234,567
123,456
12,345
1,234
123
12
1
0
(Solution: make 0 a special case, otherwise remember if there has been a
non-zero digit, supress all printing until a non-zero digit has been
encountered.
Suppose we want to read integers containing commas, ignoring the commas,
and stopping at the first blankspace. Reading into an integer variable
can't handle the task, and we have to read individual characters, building
up the value of the number from the values of the indivdiual characters.
While the ordinal values of the digit characters are not the same as their
numerical values (this is because the digits are not the first characters
in standard alphabetical order), they are consecutive, so we can read a
digit into a CHAR variable and get its numerical value DIGIT by
READ (C);
DIGIT:= ORD(C) - ORD(`O').
We get the value of a multi-digit member like 123456 from the values of its
individual digits by treating it as a polynomial
1 X 10↑5 + 2 X 10↑4 + 3 X 10↑3 + 4 X 10↑2 + 5 X 10 + 6,
or more simply
((((1 X 10 + 2) X 10 + 3) X 10 + 40 X 10+ 5) X 10 + 6.
Now the plan of the algorithm becomes clear. We read the characters of the
number, descarding commas, and keeping track of the numerical value ot the
part ot the number so far seen:
N:=0;
READ(C);
WHILE C <> ` ' DO
BEGIN
IF C <> `,' THEN
N:=N * 10 + ORD(C) - ORD('O');
READ(C);
END;
(*N CONTAINS THE NUMBER READ*)
(a blank is a zero.
(but ,,,,3,,5,0 is legal.
_Exercise_
The subprogram above fails if the number read is close to the mazimum value
MAXINT. Revise it so it can read any positive integer up to MAXINT.
_Exercise_
Revise it to detect an attempt to read a number larger than MAXINT. Why is
IF N > MAXINT THEN WRITE (`TOO BIG")
not a good approach?
_Exercise_
Revise the reading algorithm to read integers written in base 16, with the
letters A through F serving as digits with values 10 through 15.